//#########################################################
//#
//#  Titre  :  Utilitaires  Liste  Chainee  et  CHAT  LINUX  Automne  13
//#            SIF-1015  -  Systeme  d'exploitation
//#            Universite  du  Quebec  a  Trois-Rivieres
//#
//#  Auteur  : Nathan  Lachance,
//#            James  Hoffman
//#    Date  : Septembre  2013
//#
//#  Langage  : ANSI  C  on  LINUX  
//#
//#######################################

#include  "Client.h"
#define SERVER_ADDRESS "192.168.1.11"
#define SERVER_PORT 1028
int  main()  
{
    int  Menu  =  1;
    int  i  =  1;
    int  key;

    initscr();

    //Vérifie  si  le  terminal des  couleur
    Has_colors();

    //Vérifie  si  il  y  a  eu  un  erreur  lors  de  l'activation  des  couleur
    Start_color();

    //Initialise  les  pair  de  couleur
    Init_color_pairs();


    menu_Window_ptr  =  newwin(LINES,COLS,0,0);

    keypad(stdscr,TRUE);

	cbreak();

    //boucle de l'interface
    while  (true)
    {
        mvwprintw(menu_Window_ptr,4,  34,  "MSNJ");
        box(menu_Window_ptr,'#','-');            
        i  =  1;
            if(Menu  >  2)
            {
                Menu  =  1;
            }

            if(Menu  <  1)
            {
                Menu  =  2;
            }

	    //Boucle des option du menu
            while(i  <  3)
            {
                if(i  ==  Menu)
                {
                    wattroff(menu_Window_ptr,A_BOLD);
                    wattrset(menu_Window_ptr,COLOR_PAIR(BLACK_ON_WHITE));
                }
                else
                {
                    wattrset(menu_Window_ptr,0);
                }

                switch(i)
                {
                    case  1  :mvwprintw(menu_Window_ptr,9,19,"Connexion  au  serveur  de  messagerie");
                            break;				  
                    case  2  :mvwprintw(menu_Window_ptr,10,19,"Quitter  l'application");
                            break;
                }

                i  +=  1;        
            }
        
            wattrset(menu_Window_ptr,0);
            wrefresh(menu_Window_ptr);


	    //Attente de la commande du client
            key  =  wgetch(menu_Window_ptr);
    

	    //Sélection du l'option selon la commande de l'usager
            switch(key)
            {
                case  'A'  :  Menu = Menu - 1;        
                        break;
                case  'B'  :  Menu = Menu + 1;
                        break;
                case  10  :  switch(Menu)
	                     {
			        case  1  :
			            MessagerieW();
			            break;
			        case  2  :
			            Delwin(menu_Window_ptr);
			            endwin();
			            exit(EXIT_SUCCESS);
			            break;
                    	     }
                    
                        break;
            }

        wclear(menu_Window_ptr);
	wrefresh(menu_Window_ptr);   
    }
} 


//#######################################
//#
//#  Affichage  de  l'interface  de  messagerie
//#
void  MessagerieW()
{
    struct  Info_FIFO_Transaction  my_data;
    char  str[TRANSACTION_SIZE];
    int  col;

    AttenteMessage = TRUE;


	int serverFD, serverLength;
	struct sockaddr_in serverAddress;

	serverFD = socket(AF_INET, SOCK_STREAM, 0);

	serverAddress.sin_family = AF_INET;
	serverAddress.sin_addr.s_addr = inet_addr(SERVER_ADDRESS);
	serverAddress.sin_port = SERVER_PORT;
	serverLength = sizeof(serverAddress);

	//Vérifie  si  l'ouverture  du  socket sur le serveur n'a  pas  causer  d'erreur
	if(connect(serverFD, (struct sockaddr*)&serverAddress, serverLength) != -1)
	{

		my_data.pid_client  =  getpid();


	    //Création du thread de réception
	    Pthread_create(&threadLectureMessage, NULL, &RecevoirRequete, &serverFD);


	    //Creation  des  deux  fenetre  de  messagerie
	    BordurelistMessage_Window_ptr = newwin(LINES-4, COLS,0,0);
	    listMessage_Window_ptr  =  newwin(LINES-6  ,COLS - 6,1,4);
	    Requete_Window_ptr  =  newwin(4  ,COLS  ,LINES  -4,0);

	    box(BordurelistMessage_Window_ptr,'#','-');

	    char titre[20];
	    sprintf(titre,"MSNJ(pid:%u)",my_data.pid_client);

	    mvwprintw(BordurelistMessage_Window_ptr,0,(COLS/2)-strlen(titre)/2,titre);

	    //Boucle de la messagerie
	    while(strcmp(str,"bye")  !=  0)
	    {
		//Crée  une  bordure  pour  les  window
		box(Requete_Window_ptr,'#','-');

		scrollok(listMessage_Window_ptr,TRUE);        

		mvwprintw(Requete_Window_ptr,1,4,"Entrez  votre  requête  :  ");

		//Définir  la  pallette  de  couleur  pour  la  ligne  de  requete
		wattroff(Requete_Window_ptr,A_BOLD);
		wattrset(Requete_Window_ptr,COLOR_PAIR(BLACK_ON_WHITE));

		col  =  2;        

		//Avoir  la  ligne  de  requete  blanche
		while(col  <  COLS  -  2)
		{
		    mvwprintw(Requete_Window_ptr,2,col,"  ");
		    col  +=  1;
		}

		wmove(Requete_Window_ptr,2,3);

		//Refresh  les  3  window
		wrefresh(Requete_Window_ptr);
		wrefresh(listMessage_Window_ptr);
		wrefresh(BordurelistMessage_Window_ptr);


		//Attend la requete de l'usager
		wgetstr(Requete_Window_ptr,str);


		//Met la couleur par défaut
		wattrset(Requete_Window_ptr, 0);
		wattron(listMessage_Window_ptr, COLOR_PAIR(WHITE_ON_BLACK));


		//Ajout de la commande rentrer a la liste de message
		waddstr(listMessage_Window_ptr,str);
	 	waddstr(listMessage_Window_ptr, "\n");


		//Vérifie si le retour de l'usager dépasse les 300 caractère
		if(strlen(str) <= TRANSACTION_SIZE && strlen(str) > 0 && strcmp(str,"bye")  !=  0)
		{
			sprintf(my_data.transaction,  str);

			//Envoie  la  requete  au  serveur
			write(serverFD,  &my_data,  sizeof(my_data));

		}
		else
		{
			wattron(listMessage_Window_ptr, COLOR_PAIR(RED_ON_BLACK));
			waddstr(listMessage_Window_ptr, "Message invalide, le message doit etre plus grand que 0 et plus petit que 300.\n");
		}

		//Refresh les windows
		wrefresh(BordurelistMessage_Window_ptr);
		wrefresh(listMessage_Window_ptr);

		wclear(Requete_Window_ptr);
	    }
	}
	else
	{
		GestionErreurConnectionSocket();
	}


    

    AttenteMessage = FALSE;

    sprintf(my_data.transaction, DELREQUETE, my_data.pid_client);

    //Envoie  la  requete  au  serveur
    write(serverFD,  &my_data,  sizeof(my_data));

    Pthread_join(threadLectureMessage,NULL);

    close(serverFD);

    //Efface  les  deux  fenetre  de  requete  et  ce  dissocie  du  server
    Delwin(listMessage_Window_ptr);
    Delwin(Requete_Window_ptr);
    Delwin(BordurelistMessage_Window_ptr);
}



//#######################################
//#
//#  Recois  la  requete  de retour du serveur
//#
void* RecevoirRequete(void* _server)
{	
	int server = *((int*)_server);

	struct Server_Response sr;
	int byteRead = 0;

	//Boucle de lecture des requete de retour
	while(AttenteMessage)
	{    		
		//Recois la requete			
		byteRead = read(server, &sr, sizeof(sr));

		//Vérifie si la requete est valide
		if(byteRead == sizeof(sr))
		{
			//Vérifie si la requete est une Réussite ou un Échec
			if(sr.ack == 'R')
				wattron(listMessage_Window_ptr, COLOR_PAIR(GREEN_ON_BLACK));
			else
				wattron(listMessage_Window_ptr, COLOR_PAIR(RED_ON_BLACK));

			//Affiche la requete
			waddstr(listMessage_Window_ptr, sr.message);
		}	
		wrefresh(listMessage_Window_ptr);	
	}

	pthread_exit(0);
}


void GestionErreurConnectionSocket()
{
	wclear(menu_Window_ptr);
	
	waddstr(menu_Window_ptr,"\n\n>>>Il  n'y  a  aucun  serveur\n\n");
	
	wrefresh(menu_Window_ptr);

	sleep(2);

	Delwin(menu_Window_ptr);
	endwin();
    
	exit(EXIT_SUCCESS);
}


